package com.lifei.service;

import com.lifei.VO.ResultData;
import com.lifei.domain.Order;
import com.lifei.repository.OrderRepository;
import com.lifei.repository.ProductRepository;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.SessionCallback;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Random;

@Service
public class OrderService {

    @Autowired
    private OrderRepository orderRepository;
    @Autowired
    private ProductRepository productRepository;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private RocketMQTemplate rocketMQTemplate;



    public Integer submitOrder(Integer productId){
        Order orderInfo = new Order();
        orderInfo.setProductId(productId);
        orderInfo.setOrderStatus(0);
        orderInfo.setOrderNumber(getOrderNum());

        boolean flag = subtractStock(1);

        if(!flag){
            return -1;
        }
        rocketMQTemplate.convertAndSend("springboot-mq",orderInfo);
        return orderInfo.getOrderNumber();
    }


    public ResultData<Order> payOrder(Integer orderId) {
        if(checkPay(orderId) == 0) {
            return new ResultData<>(400,"订单已过期",null);
        }
        Order order = orderRepository.findOneById(orderId);
        order.setOrderStatus(1);
        order = orderRepository.save(order);
        System.out.println("... 订单支付成功 ...");
        return new ResultData<>(200,"支付成功",order);
    }

    public Integer checkPay(Integer orderId){
        Boolean delete = redisTemplate.delete("order:" + orderId);
        if(delete != null && delete){
            return 1;
        }
        return 0;
    }

    // 模拟订单号
    public Integer getOrderNum(){
        Random random = new Random();
        return random.nextInt(10000);
    }

    /**
     * Redis乐观锁实现秒杀
     * @param num 表示用户需要购买的数量
     */

    public boolean subtractStock(Integer num) {
        SessionCallback<Object>  sessionCallback = new SessionCallback<Object>(){
            @Override
            public Object execute(RedisOperations operations) throws DataAccessException{
                String key = "num";
                Object value = operations.opsForValue().get(key);
                if (value == null) {
                    // 说明没有该商品或者该商品没有放入缓存
                    return false;
                }
                //先检查 库存是否充足
                Integer stock = Integer.valueOf(value.toString());
                if (stock < num) {
                    System.out.println("... 库存不足 ...");
                    return false;
                }
                operations.watch(key);
                operations.multi(); // 开始事务
                Long newStock = operations.opsForValue().increment(key, -num.longValue());
//                System.out.println("... 操作后的新库存数量 " + newStock + " ...");
                List<Object> exec = operations.exec(); // 提交事务

                if(exec.size()>0){
                    return true;
                }
                return false;
            }
        };
        return (Boolean) redisTemplate.execute(sessionCallback);
    }




    public boolean subtractStockV2(Integer num) {
        String key = "num";
        Object value = redisTemplate.opsForValue().get(key);
        if (value == null) {
            // 说明没有该商品或者该商品没有放入缓存，这里放一下
//            redisTemplate.opsForValue().set(key,"100");
            return false;
        }
        //先检查 库存是否充足
        Integer stock = Integer.valueOf(value.toString());
        if (stock < num) {
            System.out.println("... 库存不足 ...");
            return false;
        }

        redisTemplate.setEnableTransactionSupport(true);
        redisTemplate.watch(key);
        redisTemplate.multi(); // 开始事务
        Long newStock = redisTemplate.opsForValue().increment(key, -num.longValue());
        System.out.println("... 操作后的新库存数量 " + newStock + " ...");
        List<Object> exec = redisTemplate.exec(); // 提交事务

        if(exec.size()>0){
            return true;
        }
        return false;
    }

}
